home *** CD-ROM | disk | FTP | other *** search
/ Sprite 1984 - 1993 / Sprite 1984 - 1993.iso / src / machserver / 1.098 / fsio / fsioPipe.c < prev    next >
C/C++ Source or Header  |  1991-03-30  |  34KB  |  1,161 lines

  1. /*
  2.  * fsPipe.c --
  3.  *
  4.  *    Routines for unnamed pipes.  An unnamed pipe has a fixed length
  5.  *    resident buffer, a reading stream, and a writing stream.
  6.  *    Process migration can result in remotely accessed pipes.
  7.  *
  8.  * Copyright (C) 1985 Regents of the University of California
  9.  * All rights reserved.
  10.  */
  11.  
  12. #ifndef lint
  13. static char rcsid[] = "$Header: /sprite/src/kernel/fsio/RCS/fsioPipe.c,v 9.10 91/03/30 17:10:09 mgbaker Exp $ SPRITE (Berkeley)";
  14. #endif not lint
  15.  
  16.  
  17. #include <sprite.h>
  18.  
  19. #include <fs.h>
  20. #include <fsutil.h>
  21. #include <fsio.h>
  22. #include <fsNameOps.h>
  23. #include <fsconsist.h>
  24. #include <fsStat.h>
  25. #include <fsrmt.h>
  26. #include <vm.h>
  27. #include <proc.h>
  28. #include <rpc.h>
  29. #include <fsioPipe.h>
  30.  
  31. #include <stdio.h>
  32.  
  33. /*
  34.  * Monitor to synchronize access to the openInstance in GetFileID.
  35.  */
  36. static    Sync_Lock    pipeLock = Sync_LockInitStatic("Fs:pipeLock");
  37. #define    LOCKPTR    &pipeLock
  38.  
  39. /*
  40.  * Forward references.
  41.  */
  42. static void GetFileID _ARGS_((Fs_FileID *fileIDPtr));
  43. extern Fsio_PipeIOHandle *Fsio_PipeHandleInit _ARGS_((Fs_FileID *fileIDPtr, 
  44.         Boolean findIt));
  45. static ReturnStatus PipeCloseInt _ARGS_((Fsio_PipeIOHandle *handlePtr, 
  46.         int ref, int write, Boolean release));
  47.  
  48. /*
  49.  * Migration debugging.
  50.  */
  51. #ifdef MIG_DEBUG
  52.  
  53. #define PIPE_CREATED(inStreamPtr, outStreamPtr) \
  54.     { \
  55.     printf("Create Pipe: Srvr %d Read <%d> Write <%d> I/O %d <%d,%d>\n", \
  56.         (inStreamPtr)->hdr.fileID.serverID, \
  57.         (inStreamPtr)->hdr.fileID.minor, \
  58.         (outStreamPtr)->hdr.fileID.minor, \
  59.         (inStreamPtr)->ioHandlePtr->fileID.serverID, \
  60.         (inStreamPtr)->ioHandlePtr->fileID.major, \
  61.         (inStreamPtr)->ioHandlePtr->fileID.minor); \
  62.     }
  63.  
  64. #define PIPE_CLOSE(streamPtr, handlePtr) \
  65.     printf("Pipe Close: Stream %s <%d> I/O <%d,%d> ref %d write %d flags %x\n", \
  66.         ((streamPtr)->flags & FS_READ) ? "Read" : "Write", \
  67.         (streamPtr)->hdr.fileID.minor, \
  68.         (handlePtr)->hdr.fileID.major, (handlePtr)->hdr.fileID.minor, \
  69.         (handlePtr)->use.ref, (handlePtr)->use.write, \
  70.         (handlePtr)->flags)
  71.  
  72. #define PIPE_MIG_1(migInfoPtr, dstClientID) \
  73.     printf("Pipe Migrate: %d => %d Stream %d <%d> I/O <%d,%d> migFlags %x ", \
  74.         (migInfoPtr)->srcClientID, dstClientID, \
  75.         (migInfoPtr)->streamID.serverID, (migInfoPtr)->streamID.minor, \
  76.         (migInfoPtr)->ioFileID.major, (migInfoPtr)->ioFileID.minor, \
  77.         (migInfoPtr)->flags);
  78.  
  79. #define PIPE_MIG_2(migInfoPtr, closeSrcClient, handlePtr) \
  80.     printf("=> %x\n    closeSrc %d (ref %d write %d", (migInfoPtr)->flags, \
  81.         closeSrcClient, (handlePtr)->use.ref, (handlePtr)->use.write);
  82.  
  83. #define PIPE_MIG_3(handlePtr) \
  84.     printf(" | ref %d write %d)\n", \
  85.         (handlePtr)->use.ref, (handlePtr)->use.write);
  86.  
  87. #define PIPE_MIG_END(handlePtr) \
  88.     printf("PipeMigEnd: I/O <%d,%d> ref %d write %d\n", \
  89.         (handlePtr)->hdr.fileID.major, (handlePtr)->hdr.fileID.minor, \
  90.         (handlePtr)->use.ref, (handlePtr)->use.write)
  91. #else
  92.  
  93. #define PIPE_CREATED(inStreamPtr, outStreamPtr)
  94. #define PIPE_CLOSE(streamPtr, handlePtr)
  95. #define PIPE_MIG_1(migInfoPtr, dstClientID)
  96. #define PIPE_MIG_2(migInfoPtr, closeSrcClient, handlePtr)
  97. #define PIPE_MIG_3(handlePtr)
  98. #define PIPE_MIG_END(handlePtr)
  99.  
  100. #endif /* MIG_DEBUG */
  101.  
  102. /*
  103.  *----------------------------------------------------------------------
  104.  *
  105.  * Fsio_CreatePipe --
  106.  *
  107.  *      Create an unnamed pipe.  Pointers to streams for both ends of the pipe
  108.  *    are returned in *inStreamPtrPtr and *outStreamPtrPtr.
  109.  *
  110.  * Results:
  111.  *    SUCCESS.
  112.  *
  113.  * Side effects:
  114.  *    None.
  115.  *
  116.  *----------------------------------------------------------------------
  117.  */
  118.  
  119. ReturnStatus
  120. Fsio_CreatePipe(inStreamPtrPtr, outStreamPtrPtr)
  121.     Fs_Stream **inStreamPtrPtr;        /* Return - in (reading) stream */
  122.     Fs_Stream **outStreamPtrPtr;    /* Return - out (writing) stream */
  123. {
  124.     Fs_FileID        fileID;
  125.     register Fsio_PipeIOHandle    *handlePtr;
  126.     register Fs_Stream        *streamPtr;
  127.  
  128.     /*
  129.      * Set up the I/O handle for the pipe.  The installation puts
  130.      * one reference on the I/O handle.
  131.      */
  132.  
  133.     GetFileID(&fileID);
  134.     handlePtr = Fsio_PipeHandleInit(&fileID, FALSE);
  135.     (void)Fsconsist_IOClientOpen(&handlePtr->clientList, rpc_SpriteID, FS_READ, FALSE);
  136.     (void)Fsconsist_IOClientOpen(&handlePtr->clientList, rpc_SpriteID, FS_WRITE, FALSE);
  137.  
  138.     /*
  139.      * Allocate and initialize the read, or "in", end of the stream.
  140.      */
  141.     streamPtr = Fsio_StreamCreate(rpc_SpriteID, rpc_SpriteID,
  142.                 (Fs_HandleHeader *)handlePtr,
  143.                 FS_READ | FS_USER, "read-pipe");
  144.     Fsutil_HandleUnlock(streamPtr);
  145.     *inStreamPtrPtr = streamPtr;
  146.  
  147.     /*
  148.      * Set up the writing end.  Note that we get a second reference to
  149.      * the I/O handle by duping it.
  150.      */
  151.     Fsutil_HandleUnlock(handlePtr);
  152.     (void)Fsutil_HandleDup((Fs_HandleHeader *)handlePtr);
  153.     streamPtr = Fsio_StreamCreate(rpc_SpriteID, rpc_SpriteID,
  154.             (Fs_HandleHeader *)handlePtr,
  155.             FS_WRITE | FS_APPEND | FS_USER, "write-pipe");
  156.     Fsutil_HandleUnlock(handlePtr);
  157.     Fsutil_HandleUnlock(streamPtr);
  158.     *outStreamPtrPtr = streamPtr;
  159.  
  160.     PIPE_CREATED(*inStreamPtrPtr, *outStreamPtrPtr);
  161.  
  162.     return(SUCCESS);
  163. }
  164.  
  165. /*
  166.  *----------------------------------------------------------------------
  167.  *
  168.  * GetFileID --
  169.  *
  170.  *      Get a unique file ID for the pipe.  This is a monitor to synchronize
  171.  *    access to the openInstance variable that gives us unique file
  172.  *    ids for unnamed pipes.
  173.  *
  174.  * Results:
  175.  *    Unique file ID.
  176.  *
  177.  * Side effects:
  178.  *    Open instance incremented.
  179.  *
  180.  *----------------------------------------------------------------------
  181.  */
  182.  
  183. static ENTRY void
  184. GetFileID(fileIDPtr)
  185.     Fs_FileID    *fileIDPtr;
  186. {
  187.     static int openInstance = 0;
  188.  
  189.     LOCK_MONITOR;
  190.  
  191.     fileIDPtr->type = FSIO_LCL_PIPE_STREAM;
  192.     fileIDPtr->serverID = rpc_SpriteID;
  193.     fileIDPtr->major = 0;
  194.     fileIDPtr->minor = openInstance;
  195.     openInstance++;
  196.  
  197.     UNLOCK_MONITOR;
  198. }
  199.  
  200. /*
  201.  *----------------------------------------------------------------------
  202.  *
  203.  * Fsio_PipeHandleInit --
  204.  *
  205.  *    Initialize a handle for a pipe.
  206.  *
  207.  * Results:
  208.  *    A pointer to the pipe handle.
  209.  *
  210.  * Side effects:
  211.  *    Create and install a handle for the file.  It is returned locked
  212.  *    and with its reference count incremented if SUCCESS is returned.
  213.  *
  214.  *----------------------------------------------------------------------
  215.  */
  216. Fsio_PipeIOHandle *
  217. Fsio_PipeHandleInit(fileIDPtr, findIt)
  218.     Fs_FileID    *fileIDPtr;    /* Pipe file ID */
  219.     Boolean    findIt;        /* TRUE if we expect to find its handle */
  220. {
  221.     Fs_HandleHeader *hdrPtr;
  222.     register Fsio_PipeIOHandle *handlePtr;
  223.     register Boolean found;
  224.  
  225.     found = Fsutil_HandleInstall(fileIDPtr, sizeof(Fsio_PipeIOHandle), "pipe",
  226.         FALSE, &hdrPtr);
  227.     handlePtr = (Fsio_PipeIOHandle *)hdrPtr;
  228.     if (!found) {
  229.     if (findIt) {
  230.         panic( "Fsio_PipeHandleInit, didn't find handle\n");
  231.     }
  232.     /*
  233.      * When a pipe is created, it has one read and one write
  234.      * reference on the handle.
  235.      */
  236.     handlePtr->use.ref = 2;
  237.     handlePtr->use.write = 1;
  238.     handlePtr->use.exec = 0;
  239.     List_Init(&handlePtr->clientList);
  240.     handlePtr->flags = 0;
  241.     handlePtr->firstByte = handlePtr->lastByte = -1;
  242.     handlePtr->buffer = (Address)malloc(FS_BLOCK_SIZE);
  243.     handlePtr->bufSize = FS_BLOCK_SIZE;
  244.     List_Init(&handlePtr->readWaitList);
  245.     List_Init(&handlePtr->writeWaitList);
  246.     fs_Stats.object.pipes++;
  247.     }
  248.     return(handlePtr);
  249. }
  250.  
  251. /*
  252.  *----------------------------------------------------------------------
  253.  *
  254.  * Fsio_PipeClose --
  255.  *
  256.  *      Close a local pipe.  Other processes waiting on the pipe are
  257.  *    unblocked and the pipe's buffer is freed when the last
  258.  *    user goes away.
  259.  *
  260.  * Results:
  261.  *      SUCCESS.
  262.  *
  263.  * Side effects:
  264.  *      Unblock local waiting reader (or writer) waiting on the pipe.
  265.  *
  266.  *----------------------------------------------------------------------
  267.  */
  268. /*ARGSUSED*/
  269. #ifndef SOSP91
  270. ReturnStatus
  271. Fsio_PipeClose(streamPtr, clientID, procID, flags, dataSize, closeData)
  272. #else
  273. ReturnStatus
  274. Fsio_PipeClose(streamPtr, clientID, procID, flags, dataSize, closeData,
  275.     offsetPtr, rwFlagsPtr)
  276. #endif
  277.     Fs_Stream        *streamPtr;    /* Stream to a pipe */
  278.     int            clientID;    /* Host ID of closing process */
  279.     Proc_PID        procID;        /* Process closing */
  280.     int            flags;        /* Flags from the stream being closed */
  281.     int            dataSize;    /* Should be 0 */
  282.     ClientData        closeData;    /* Should be NIL */
  283. #ifdef SOSP91
  284.     int            *offsetPtr;    /* Not used. */
  285.     int            *rwFlagsPtr;    /* Not used. */
  286. #endif
  287.  
  288. {
  289.     register Fsio_PipeIOHandle *handlePtr = 
  290.         (Fsio_PipeIOHandle *)streamPtr->ioHandlePtr;
  291.     Boolean cache = FALSE;
  292.     ReturnStatus status;
  293.  
  294.     if (!Fsconsist_IOClientClose(&handlePtr->clientList, clientID, flags, &cache)) {
  295.     printf( "Fsio_PipeClose, unknown client %d\n", clientID);
  296.     Fsutil_HandleUnlock(handlePtr);
  297.     } else {
  298.     PIPE_CLOSE(streamPtr, handlePtr);
  299.     status = PipeCloseInt(handlePtr, 1, (flags & FS_WRITE) != 0, TRUE);
  300.     if (status != FS_FILE_REMOVED) {
  301.         Fsutil_HandleRelease(handlePtr, TRUE);
  302.     }
  303.     }
  304.     return(SUCCESS);
  305. }
  306.  
  307. /*
  308.  *----------------------------------------------------------------------
  309.  *
  310.  * PipeCloseInt --
  311.  *
  312.  *      Do the real work of closing a pipe, given a variable number
  313.  *    of references. 
  314.  *
  315.  * Results:
  316.  *      SUCCESS or FS_FILE_REMOVED, which indicates that the pipe has been
  317.  *     freed up.
  318.  *
  319.  * Side effects:
  320.  *      Unblock local waiting reader (or writer) waiting on the pipe.
  321.  *
  322.  *----------------------------------------------------------------------
  323.  */
  324. /*ARGSUSED*/
  325. static ReturnStatus
  326. PipeCloseInt(handlePtr, ref, write, release)
  327.     Fsio_PipeIOHandle *handlePtr;    /* Pipe to clean up */
  328.     int ref;                /* Number of uses to remove */
  329.     int write;                /* Number of writers to remove */
  330.     Boolean release;            /* Whether to release handle to
  331.                        remove it. */
  332. {
  333.     /*
  334.      * Update the global/summary use counts for the file.
  335.      */
  336.     handlePtr->use.ref -= ref;
  337.     handlePtr->use.write -= write;
  338.     if (handlePtr->use.ref < 0 || handlePtr->use.write < 0) {
  339.     panic("PipeCloseInt <%d,%d> use %d, write %d\n",
  340.           handlePtr->hdr.fileID.major, handlePtr->hdr.fileID.minor,
  341.           handlePtr->use.ref, handlePtr->use.write);
  342.     }
  343.     if (write && handlePtr->use.write == 0) {
  344.     /*
  345.      * Notify reader that the writer has closed.
  346.      */
  347.     handlePtr->flags |= FSIO_PIPE_WRITER_GONE;
  348.     Fsutil_FastWaitListNotify(&handlePtr->readWaitList);
  349.     } else if (ref && handlePtr->use.ref == handlePtr->use.write) {
  350.     /*
  351.      * Update state and notify any blocked writers.  Their write
  352.      * will fail with no remaining readers.
  353.      */
  354.     handlePtr->flags |= FSIO_PIPE_READER_GONE;
  355.     Fsutil_FastWaitListNotify(&handlePtr->writeWaitList);
  356.     }
  357.     if (handlePtr->flags == (FSIO_PIPE_WRITER_GONE|FSIO_PIPE_READER_GONE)) {
  358.     free(handlePtr->buffer);
  359.     Fsutil_WaitListDelete(&handlePtr->readWaitList);
  360.     Fsutil_WaitListDelete(&handlePtr->writeWaitList);
  361.     if (release) {
  362.         Fsutil_HandleRelease(handlePtr, FALSE);
  363.     }
  364.     Fsutil_HandleRemove(handlePtr);
  365.     fs_Stats.object.pipes--;
  366.     return (FS_FILE_REMOVED);
  367.     }
  368.     /*
  369.      * Handle will be released or unlocked by caller as appropriate.
  370.      */
  371.     return(SUCCESS);
  372. }
  373.  
  374. /*
  375.  *----------------------------------------------------------------------
  376.  *
  377.  * Fsio_PipeRead --
  378.  *
  379.  *      Read on a pipe.  Data is copied out of the pipe to satisfy the
  380.  *    read.  If the pipe is empty this routine returns FS_WOULD_BLOCK.
  381.  *    If the pipe writer is gone this returns SUCCESS and 0 bytes
  382.  *    to simulate EOF.
  383.  *
  384.  * Results:
  385.  *      SUCCESS unless there was an address error or I/O error.
  386.  *
  387.  * Side effects:
  388.  *      Fill in the buffer.  Notifies the pipe's writeWaitList after
  389.  *    removing data from the pipe.
  390.  *
  391.  *----------------------------------------------------------------------
  392.  */
  393. /*ARGSUSED*/
  394. ReturnStatus
  395. Fsio_PipeRead(streamPtr, readPtr, waitPtr, replyPtr)
  396.     Fs_Stream           *streamPtr;     /* Stream to read from */
  397.     Fs_IOParam        *readPtr;    /* Read parameter block. */
  398.     Sync_RemoteWaiter    *waitPtr;    /* Process info for remote waiting */
  399.     Fs_IOReply        *replyPtr;    /* Signal to return, if any,
  400.                      * plus the amount read. */
  401. {
  402.     ReturnStatus     status = SUCCESS;
  403.     register Fsio_PipeIOHandle *handlePtr =
  404.         (Fsio_PipeIOHandle *)streamPtr->ioHandlePtr;
  405.     int         toRead;
  406.     int         startOffset;
  407.     int            startByte;
  408.     int            endByte;
  409.  
  410.     Fsutil_HandleLock(handlePtr);
  411.  
  412.     if (handlePtr->firstByte == -1) {
  413.     /*
  414.      * No data in the pipe.  If there is no writer left then
  415.      * return SUCCESS so the user process thinks of it as end of file,
  416.      * otherwise block waiting for input.
  417.      */
  418.     replyPtr->length = 0;
  419.     if (handlePtr->flags & FSIO_PIPE_WRITER_GONE) {
  420.         status = SUCCESS;
  421.         goto exit;
  422.     } else {
  423.         status = FS_WOULD_BLOCK;
  424.         goto exit;
  425.     }
  426.     }
  427.     /*
  428.      * Compute the number of bytes that we can read from the pipe.  
  429.      */
  430.     toRead = handlePtr->lastByte - handlePtr->firstByte + 1;
  431.     if (toRead > readPtr->length) {
  432.     toRead = readPtr->length;
  433.     }
  434.  
  435.     /*
  436.      * Compute offsets into the pipe buffer.  The offsets float out past
  437.      * the size of the buffer, but we use masks to take of the top bits.
  438.      * We can also compare these top bits to determine if the valid range
  439.      * of the buffer wraps around the end of the pipe.
  440.      */
  441.     startByte = handlePtr->firstByte;
  442.     startOffset = startByte & FS_BLOCK_OFFSET_MASK;
  443.     endByte = handlePtr->firstByte + toRead - 1;
  444.  
  445.     if ((startByte & ~FS_BLOCK_OFFSET_MASK) ==
  446.     (endByte & ~FS_BLOCK_OFFSET_MASK)) {
  447.     /*
  448.      * Can do a straight copy, no wrap around necessary.
  449.      */
  450.     if (readPtr->flags & FS_USER) {
  451.         if (Vm_CopyOut(toRead, handlePtr->buffer + startOffset, readPtr->buffer)
  452.               != SUCCESS) {
  453.         status = SYS_ARG_NOACCESS;
  454.         }
  455.     } else {
  456.         bcopy(handlePtr->buffer + startOffset, readPtr->buffer, toRead);
  457.     }
  458.     } else {
  459.     int    numBytes;
  460.     /*
  461.      * Have to wrap around in the block so do it in two copies.
  462.      */
  463.     numBytes = FS_BLOCK_SIZE - startOffset;
  464.     if (readPtr->flags & FS_USER) {
  465.         if (Vm_CopyOut(numBytes, handlePtr->buffer + startOffset, readPtr->buffer)
  466.               != SUCCESS) {
  467.         status = SYS_ARG_NOACCESS;
  468.         } else if (Vm_CopyOut(toRead - numBytes, handlePtr->buffer,
  469.                 readPtr->buffer + numBytes) != SUCCESS) {
  470.         status = SYS_ARG_NOACCESS;
  471.         }
  472.     } else {
  473.         bcopy(handlePtr->buffer + startOffset, readPtr->buffer, numBytes);
  474.         bcopy(handlePtr->buffer, readPtr->buffer + numBytes, toRead - numBytes);
  475.     }
  476.     }
  477.  
  478.     /*
  479.      * We just made space in the pipe so wake up blocked writers.
  480.      */
  481.     Fsutil_FastWaitListNotify(&handlePtr->writeWaitList);
  482.  
  483.     /*
  484.      * Update the first byte and the parameters.
  485.      */
  486.     handlePtr->firstByte += toRead;
  487.     if (handlePtr->firstByte > handlePtr->lastByte) {
  488.     handlePtr->firstByte = -1;
  489.     handlePtr->lastByte = -1;
  490.     }
  491.     replyPtr->length = toRead;
  492. exit:
  493.     if (status == FS_WOULD_BLOCK) {
  494.     Fsutil_FastWaitListInsert(&handlePtr->readWaitList, waitPtr);
  495.     }
  496.     Fsutil_HandleUnlock(handlePtr);
  497.     return(status);
  498. }
  499.  
  500.  
  501. /*
  502.  *----------------------------------------------------------------------
  503.  *
  504.  * Fsio_PipeWrite --
  505.  *
  506.  *      Write on a pipe.  This will put as much data as possible into the
  507.  *    pipe buffer, and then block the process (return would-block) if
  508.  *    there is any left over data.  *lenPtr is updated to reflect how
  509.  *    much data was written to the pipe.
  510.  *
  511.  * Results:
  512.  *      SUCCESS unless there was an address error or I/O error.
  513.  *
  514.  * Side effects:
  515.  *      Fill the pipe from the buffer.
  516.  *
  517.  *----------------------------------------------------------------------
  518.  */
  519. ReturnStatus
  520. Fsio_PipeWrite(streamPtr, writePtr, waitPtr, replyPtr)
  521.     Fs_Stream           *streamPtr;     /* Stream to write to */
  522.     Fs_IOParam        *writePtr;    /* Read parameter block */
  523.     Sync_RemoteWaiter    *waitPtr;    /* Process info for remote waiting */
  524.     Fs_IOReply        *replyPtr;    /* Signal to return, if any */
  525. {
  526.     register ReturnStatus     status = SUCCESS;
  527.     register Fsio_PipeIOHandle    *handlePtr =
  528.         (Fsio_PipeIOHandle *)streamPtr->ioHandlePtr;
  529.     int             startOffset;
  530.     register int         toWrite;
  531.     int                startByte;
  532.     int                endByte;
  533.  
  534.     Fsutil_HandleLock(handlePtr);
  535.  
  536.     if (handlePtr->flags & FSIO_PIPE_READER_GONE) {
  537.     replyPtr->length = 0;
  538.     replyPtr->signal = SIG_PIPE;
  539.     status = FS_BROKEN_PIPE;
  540.     goto exit;
  541.     }
  542.  
  543.     /*
  544.      * Compute the number of bytes that will fit in the pipe.  Remember
  545.      * that the pipe can only hold one block of data.
  546.      */
  547.     if (handlePtr->firstByte == -1) {
  548.     toWrite = FS_BLOCK_SIZE;
  549.     } else {
  550.     toWrite = FS_BLOCK_SIZE - 
  551.             (handlePtr->lastByte - handlePtr->firstByte + 1);
  552.     }
  553.     if (toWrite == 0) {
  554.     /*
  555.      * No room in the pipe.
  556.      */
  557.     replyPtr->length = 0;
  558.     status = FS_WOULD_BLOCK;
  559.     goto exit;
  560.     } else if (toWrite > writePtr->length) {
  561.     toWrite = writePtr->length;
  562.     } else if (writePtr->length > toWrite) {
  563.     /*
  564.      * If there is more data to write we must block after writing the
  565.      * data that we can.  
  566.      */
  567.     status = FS_WOULD_BLOCK;
  568.     }
  569.     /*
  570.      * Determine where to start and stop writing.  Note that the firstByte
  571.      * and lastByte offsets float out beyond the size of the pipe but
  572.      * we use masks to clear off the extra high order bits.
  573.      */
  574.     startByte = handlePtr->lastByte + 1;
  575.     startOffset = startByte & FS_BLOCK_OFFSET_MASK;
  576.     endByte = handlePtr->lastByte + toWrite;
  577.  
  578.     if ((startByte & ~FS_BLOCK_OFFSET_MASK) ==
  579.     (endByte & ~FS_BLOCK_OFFSET_MASK)) {
  580.     /*
  581.      * Can do a straight copy, no wrap around necessary.
  582.      */
  583.     if (writePtr->flags & FS_USER) {
  584.         if (Vm_CopyIn(toWrite, writePtr->buffer, handlePtr->buffer + startOffset)
  585.               != SUCCESS) {
  586.         status = SYS_ARG_NOACCESS;
  587.         }
  588.     } else {
  589.         bcopy(writePtr->buffer, handlePtr->buffer + startOffset, toWrite);
  590.     }
  591.     } else {
  592.     int    numBytes;
  593.     /*
  594.      * Have to wrap around in the block so do it in two copies.
  595.      */
  596.     numBytes = FS_BLOCK_SIZE - startOffset;
  597.     if (writePtr->flags & FS_USER) {
  598.         if (Vm_CopyIn(numBytes, writePtr->buffer, handlePtr->buffer + startOffset)
  599.               != SUCCESS) {
  600.         status = SYS_ARG_NOACCESS;
  601.         } else if (Vm_CopyIn(toWrite - numBytes, writePtr->buffer + numBytes, 
  602.                 handlePtr->buffer) != SUCCESS) {
  603.         status = SYS_ARG_NOACCESS;
  604.         }
  605.     } else {
  606.         bcopy(writePtr->buffer, handlePtr->buffer + startOffset, numBytes);
  607.         bcopy(writePtr->buffer + numBytes, handlePtr->buffer, toWrite - numBytes);
  608.     }
  609.     }
  610.  
  611.     /*
  612.      * We just wrote to the pipe so wake up blocked readers.
  613.      */
  614.     Fsutil_FastWaitListNotify(&handlePtr->readWaitList);
  615.  
  616.     /*
  617.      * Update first byte, last byte and the parameters.
  618.      */
  619.     if (handlePtr->firstByte == -1) {
  620.     handlePtr->firstByte = 0;
  621.     }
  622.     handlePtr->lastByte = endByte;
  623.     replyPtr->length = toWrite;
  624. exit:
  625.     if (status == FS_WOULD_BLOCK) {
  626.     Fsutil_FastWaitListInsert(&handlePtr->writeWaitList, waitPtr);
  627.     }
  628.     Fsutil_HandleUnlock(handlePtr);
  629.     return(status);
  630. }
  631.  
  632.  
  633. /*
  634.  *----------------------------------------------------------------------
  635.  *
  636.  * Fsio_PipeIOControl --
  637.  *
  638.  *    Check the IOC_CLEAR_FLAG control, and allow the IOC_SET_FLAG control.
  639.  *
  640.  * Results:
  641.  *      SUCCESS unless they try to clear the FS_APPEND flag.
  642.  *
  643.  * Side effects:
  644.  *      None.
  645.  *
  646.  *----------------------------------------------------------------------
  647.  */
  648. /*ARGSUSED*/
  649. ReturnStatus
  650. Fsio_PipeIOControl(streamPtr, ioctlPtr, replyPtr)
  651.     Fs_Stream *streamPtr;
  652.     Fs_IOCParam *ioctlPtr;        /* I/O Control parameter block */
  653.     Fs_IOReply *replyPtr;        /* Return length and signal */
  654. {
  655.     register Fsio_PipeIOHandle *handlePtr =
  656.         (Fsio_PipeIOHandle *)streamPtr->ioHandlePtr;
  657.     register int command = ioctlPtr->command;
  658.     ReturnStatus status = SUCCESS;
  659.  
  660.     switch(command) {
  661.     case IOC_REPOSITION:
  662.         return(FS_BAD_SEEK);
  663.     case IOC_GET_FLAGS:
  664.     case IOC_SET_BITS:
  665.         return(SUCCESS);
  666.     case IOC_CLEAR_BITS:
  667.     case IOC_SET_FLAGS: {
  668.         /*
  669.          * Guard against turning off append mode in pipes.
  670.          */
  671.         int flags;
  672.         int size;
  673.         int inSize;
  674.  
  675.         if (ioctlPtr->inBufSize != sizeof(int)) {
  676.         status = GEN_INVALID_ARG;
  677.         } else if (ioctlPtr->format != mach_Format) {
  678.         int fmtStatus;
  679.         size = sizeof(int);
  680.         inSize = ioctlPtr->inBufSize;
  681.         fmtStatus = Fmt_Convert("w", ioctlPtr->format, &inSize,
  682.                 ioctlPtr->inBuffer, mach_Format, &size,
  683.                 (Address) &flags);
  684.         if (fmtStatus != 0) {
  685.             printf("Format of ioctl failed <0x%x>\n", fmtStatus);
  686.             status = GEN_INVALID_ARG;
  687.         }
  688.         if (size != sizeof(int)) {
  689.             status = GEN_INVALID_ARG;
  690.         }
  691.         } else {
  692.         flags = *(int *)ioctlPtr->inBuffer;
  693.         }
  694.         if (status != SUCCESS) {
  695.         return(status);
  696.         }
  697.         if ((command == IOC_SET_FLAGS && (flags & IOC_APPEND) == 0) ||
  698.         (command == IOC_CLEAR_BITS && (flags & IOC_APPEND))) {
  699.         return(GEN_INVALID_ARG);
  700.         }
  701.         return(SUCCESS);
  702.     }
  703.     case IOC_TRUNCATE:
  704.     case IOC_LOCK:
  705.     case IOC_UNLOCK:
  706.         return(GEN_NOT_IMPLEMENTED);
  707.     case IOC_NUM_READABLE: {
  708.         int bytesAvailable = handlePtr->lastByte - handlePtr->firstByte;
  709.  
  710.         if (ioctlPtr->outBufSize != sizeof(int)) {
  711.         status = GEN_INVALID_ARG;
  712.         } else if (ioctlPtr->format != mach_Format) {
  713.         int size = sizeof(int);
  714.         int inSize = sizeof(int);
  715.         int fmtStatus;
  716.         fmtStatus = Fmt_Convert("w", mach_Format, &inSize,
  717.                 (Address) &bytesAvailable, ioctlPtr->format, 
  718.                 &size, (Address) ioctlPtr->outBuffer);
  719.         if (fmtStatus != 0) {
  720.             printf("Format of ioctl failed <0x%x>\n", fmtStatus);
  721.             status = GEN_INVALID_ARG;
  722.         }
  723.         if (size != sizeof(int)) {
  724.             status = GEN_INVALID_ARG;
  725.         }
  726.         } else {
  727.         *(int *)ioctlPtr->outBuffer = bytesAvailable;
  728.         }
  729.         return(status);
  730.     }
  731.     case IOC_GET_OWNER:
  732.     case IOC_SET_OWNER:
  733.     case IOC_MAP:
  734.     case IOC_PREFIX:
  735.         return(GEN_NOT_IMPLEMENTED);
  736.     default:
  737.         return(GEN_INVALID_ARG);
  738.     }
  739. }
  740.  
  741. /*
  742.  *----------------------------------------------------------------------
  743.  *
  744.  * Fsio_PipeSelect --
  745.  *
  746.  *    Select on a pipe.
  747.  *
  748.  * Results:
  749.  *      SUCCESS unless there was an address error or I/O error.
  750.  *
  751.  * Side effects:
  752.  *      Fill the pipe from the buffer.
  753.  *
  754.  *----------------------------------------------------------------------
  755.  */
  756. ReturnStatus
  757. Fsio_PipeSelect(hdrPtr, waitPtr, readPtr, writePtr, exceptPtr)
  758.     Fs_HandleHeader *hdrPtr;    /* The handle of the file */
  759.     Sync_RemoteWaiter *waitPtr;    /* Process info for waiting */
  760.     int        *readPtr;    /* Read bit */
  761.     int        *writePtr;    /* Write bit */
  762.     int        *exceptPtr;    /* Exception bit */
  763. {
  764.     register Fsio_PipeIOHandle *handlePtr = (Fsio_PipeIOHandle *)hdrPtr;
  765.  
  766.     Fsutil_HandleLock(hdrPtr);
  767.     *exceptPtr = 0;
  768.     if (*writePtr) {
  769.     /*
  770.      * Turn off writability if the pipe is full and there
  771.      * are still readers.  If there are no readers we allow
  772.      * writing but the next write will fail.
  773.      */
  774.     if ((((handlePtr->firstByte + 1) % FS_BLOCK_SIZE) ==
  775.          handlePtr->lastByte) && 
  776.          ((handlePtr->flags & FSIO_PIPE_READER_GONE) == 0)) {
  777.         if (waitPtr != (Sync_RemoteWaiter *)NIL) {
  778.         Fsutil_FastWaitListInsert(&handlePtr->writeWaitList, waitPtr);
  779.         }
  780.         *writePtr = 0;
  781.     }
  782.     }
  783.     if (*readPtr) {
  784.     /*
  785.      * If there's data to be read then set the READABLE bit.
  786.      * If all the writers have died, then this process will never be 
  787.      * woken up again so lie and say the pipe is readble. The process
  788.      * discover there's no writer when it tries to read the pipe.
  789.      */
  790.     if ((handlePtr->firstByte == -1) &&
  791.         ((handlePtr->flags & FSIO_PIPE_WRITER_GONE) == 0)) {
  792.         *readPtr = 0;
  793.         if (waitPtr != (Sync_RemoteWaiter *)NIL) {
  794.         Fsutil_FastWaitListInsert(&handlePtr->readWaitList, waitPtr);
  795.         }
  796.         }
  797.     }
  798.     Fsutil_HandleUnlock(hdrPtr);
  799.     return(SUCCESS);
  800. }
  801.  
  802. /*
  803.  *----------------------------------------------------------------------
  804.  *
  805.  * Fsio_PipeGetIOAttr --
  806.  *
  807.  *    Get the most up-to-date I/O attributes for a pipe.
  808.  *
  809.  * Results:
  810.  *    SUCCESS
  811.  *
  812.  * Side effects:
  813.  *      Updates the first and last byte indexes of the handle.
  814.  *
  815.  *----------------------------------------------------------------------
  816.  */
  817. /*ARGSUSED*/
  818. ReturnStatus
  819. Fsio_PipeGetIOAttr(fileIDPtr, clientID, attrPtr)
  820.     Fs_FileID            *fileIDPtr;    /* FileID of pipe */
  821.     int             clientID;    /* IGNORED */
  822.     register Fs_Attributes    *attrPtr;    /* Attributes to update */
  823. {
  824.     Fsio_PipeIOHandle *handlePtr;
  825.  
  826.     handlePtr = Fsutil_HandleFetchType(Fsio_PipeIOHandle, fileIDPtr);
  827.     if (handlePtr != (Fsio_PipeIOHandle *)NIL) {
  828.     attrPtr->serverID    = fileIDPtr->serverID;
  829.     attrPtr->domain        = fileIDPtr->major;
  830.     attrPtr->fileNumber    = fileIDPtr->minor;
  831.     attrPtr->type        = FS_LOCAL_PIPE;
  832.     attrPtr->size        = handlePtr->lastByte - handlePtr->firstByte +1;
  833.     attrPtr->devServerID    = fileIDPtr->serverID;
  834.     Fsutil_HandleRelease(handlePtr, TRUE);
  835.     }
  836.     return(SUCCESS);
  837. }
  838.  
  839. /*
  840.  *----------------------------------------------------------------------
  841.  *
  842.  * Fsio_PipeSetIOAttr --
  843.  *
  844.  *    Set the I/O attributes for a pipe.  This doesn't do anything.
  845.  *
  846.  * Results:
  847.  *    SUCCESS
  848.  *
  849.  * Side effects:
  850.  *      Updates the first and last byte indexes of the handle.
  851.  *
  852.  *----------------------------------------------------------------------
  853.  */
  854. /*ARGSUSED*/
  855. ReturnStatus
  856. Fsio_PipeSetIOAttr(fileIDPtr, attrPtr, flags)
  857.     Fs_FileID        *fileIDPtr;    /* FileID of pipe */
  858.     Fs_Attributes    *attrPtr;    /* Attributes to update */
  859.     int            flags;        /* What attrs to set */
  860. {
  861.     return(SUCCESS);
  862. }
  863.  
  864. /*
  865.  * ----------------------------------------------------------------------------
  866.  *
  867.  * Fsio_PipeMigClose --
  868.  *
  869.  *    Release a reference on a Pipe I/O handle.
  870.  *    
  871.  * Results:
  872.  *    SUCCESS.
  873.  *
  874.  * Side effects:
  875.  *    Release the I/O handle.
  876.  *
  877.  * ----------------------------------------------------------------------------
  878.  *
  879.  */
  880. /*ARGSUSED*/
  881. ReturnStatus
  882. Fsio_PipeMigClose(hdrPtr, flags)
  883.     Fs_HandleHeader *hdrPtr;    /* File being released */
  884.     int flags;            /* Use flags from the stream */
  885. {
  886.     panic("Fsio_PipeMigClose called\n");
  887.     Fsutil_HandleRelease(hdrPtr, FALSE);
  888.     return(SUCCESS);
  889. }
  890.  
  891. /*
  892.  * ----------------------------------------------------------------------------
  893.  *
  894.  * Fsio_PipeMigrate --
  895.  *
  896.  *    This takes care of transfering references from one client to the other.
  897.  *    A useful side-effect of this routine is    to properly set the type in
  898.  *    the ioFileID, either FSIO_LCL_PIPE_STREAM or FSIO_RMT_PIPE_STREAM.
  899.  *    In the latter case FsrmtPipeMigrate is called to do all the work.
  900.  *
  901.  * Results:
  902.  *    An error status if the I/O handle can't be set-up.
  903.  *    Otherwise SUCCESS is returned, *flagsPtr may have the FS_RMT_SHARED
  904.  *    bit set, and *sizePtr and *dataPtr are set to reference Fsio_DeviceState.
  905.  *
  906.  * Side effects:
  907.  *    Sets the correct stream type on the ioFileID.
  908.  *    Shifts client references from the srcClient to the destClient.
  909.  *
  910.  * ----------------------------------------------------------------------------
  911.  *
  912.  */
  913. /*ARGSUSED*/
  914. ReturnStatus
  915. Fsio_PipeMigrate(migInfoPtr, dstClientID, flagsPtr, offsetPtr, sizePtr, dataPtr)
  916.     Fsio_MigInfo    *migInfoPtr;    /* Migration state */
  917.     int        dstClientID;    /* ID of target client */
  918.     int        *flagsPtr;    /* In/Out Stream usage flags */
  919.     int        *offsetPtr;    /* Return - new stream offset (not needed) */
  920.     int        *sizePtr;    /* Return - sizeof(Fsio_DeviceState) */
  921.     Address    *dataPtr;    /* Return - pointer to Fsio_DeviceState */
  922. {
  923.     Fsio_PipeIOHandle            *handlePtr;
  924.     Boolean                closeSrcClient;
  925.  
  926.     if (migInfoPtr->ioFileID.serverID != rpc_SpriteID) {
  927.     /*
  928.      * The pipe was local, which is usually true, but is now remote.
  929.      */
  930.     migInfoPtr->ioFileID.type = FSIO_RMT_PIPE_STREAM;
  931.     return(FsrmtPipeMigrate(migInfoPtr, dstClientID, flagsPtr, offsetPtr,
  932.         sizePtr, dataPtr));
  933.     }
  934.     migInfoPtr->ioFileID.type = FSIO_LCL_PIPE_STREAM;
  935.     handlePtr = Fsio_PipeHandleInit(&migInfoPtr->ioFileID, TRUE);
  936.  
  937.     PIPE_MIG_1(migInfoPtr, dstClientID);
  938.     /*
  939.      * At the stream level, add the new client to the set of clients
  940.      * for the stream, and check for any cross-network stream sharing.
  941.      */
  942.     Fsio_StreamMigClient(migInfoPtr, dstClientID, (Fs_HandleHeader *)handlePtr,
  943.             &closeSrcClient);
  944.     PIPE_MIG_2(migInfoPtr, closeSrcClient, handlePtr);
  945.  
  946.     /*
  947.      * Adjust use counts on the I/O handle to reflect any new sharing.
  948.      */
  949.     Fsio_MigrateUseCounts(migInfoPtr->flags, closeSrcClient, &handlePtr->use);
  950.     PIPE_MIG_3(handlePtr);
  951.  
  952.     /*
  953.      * Move the client at the I/O handle level.
  954.      */
  955.     Fsio_MigrateClient(&handlePtr->clientList, migInfoPtr->srcClientID,
  956.             dstClientID, migInfoPtr->flags, closeSrcClient);
  957.  
  958.     *sizePtr = 0;
  959.     *dataPtr = (Address)NIL;
  960.     *flagsPtr = migInfoPtr->flags;
  961.     *offsetPtr = migInfoPtr->offset;
  962.     /*
  963.      * We don't need this reference on the I/O handle; there is no change.
  964.      */
  965.     Fsutil_HandleRelease(handlePtr, TRUE);
  966.     return(SUCCESS);
  967. }
  968.  
  969. /*
  970.  * ----------------------------------------------------------------------------
  971.  *
  972.  * Fsio_PipeMigOpen --
  973.  *
  974.  *    Complete setup of a FSIO_LCL_PIPE_STREAM after migration (back) to the
  975.  *    pipe I/O server.  Fsio_PipeMigrate has done the work of shifting use
  976.  *    counts at the stream and I/O handle level.  This routine has to
  977.  *    increment the low level reference count on the pipe I/O handle
  978.  *    to reflect the existence of a new stream to the I/O handle.
  979.  *
  980.  * Results:
  981.  *    None.
  982.  *
  983.  * Side effects:
  984.  *    None.
  985.  *
  986.  * ----------------------------------------------------------------------------
  987.  *
  988.  */
  989. /*ARGSUSED*/
  990. ReturnStatus
  991. Fsio_PipeMigOpen(migInfoPtr, size, data, hdrPtrPtr)
  992.     Fsio_MigInfo    *migInfoPtr;    /* Migration state */
  993.     int        size;        /* Zero */
  994.     ClientData    data;        /* NIL */
  995.     Fs_HandleHeader **hdrPtrPtr;    /* Return - handle for the file */
  996. {
  997.     register Fsio_PipeIOHandle *handlePtr;
  998.  
  999.     handlePtr = Fsutil_HandleFetchType(Fsio_PipeIOHandle, &migInfoPtr->ioFileID);
  1000.     if (handlePtr == (Fsio_PipeIOHandle *)NIL) {
  1001.     panic( "Fsio_PipeMigOpen, no handle\n");
  1002.     return(FAILURE);
  1003.     } else {
  1004.     PIPE_MIG_END(handlePtr);
  1005.     Fsutil_HandleUnlock(handlePtr);
  1006.     *hdrPtrPtr = (Fs_HandleHeader *)handlePtr;
  1007.     return(SUCCESS);
  1008.     }
  1009. }
  1010.  
  1011. /*
  1012.  *----------------------------------------------------------------------
  1013.  *
  1014.  * Fsio_PipeReopen --
  1015.  *
  1016.  *    Reopen a pipe for a client.  This executed on a server and will
  1017.  *    only work if it was a network partition that made us forget
  1018.  *    about the client.  If we've already removed the pipe handle
  1019.  *    then the clien't won't be able to recover.
  1020.  *
  1021.  * Results:
  1022.  *    A  non-SUCCESS return code if the re-open failed.
  1023.  *
  1024.  * Side effects:
  1025.  *    Adds the client to the set of client's for the pipe.
  1026.  *
  1027.  *----------------------------------------------------------------------
  1028.  */
  1029. /*ARGSUSED*/
  1030. ReturnStatus
  1031. Fsio_PipeReopen(hdrPtr, clientID, inData, outSizePtr, outDataPtr)
  1032.     Fs_HandleHeader    *hdrPtr;        /* NIL */
  1033.     int            clientID;        /* Host ID of client */
  1034.     ClientData        inData;            /* sizeof Fsio_PipeReopenParams */
  1035.     int            *outSizePtr;        /* Returns 0 */
  1036.     ClientData        *outDataPtr;        /* Returns NIL */
  1037. {
  1038.     register Fsio_PipeIOHandle    *handlePtr;
  1039.     ReturnStatus        status;
  1040.     Fsio_PipeReopenParams        *reopenParamsPtr;
  1041.  
  1042.     reopenParamsPtr = (Fsio_PipeReopenParams *)inData;
  1043.     handlePtr = Fsutil_HandleFetchType(Fsio_PipeIOHandle, &reopenParamsPtr->fileID);
  1044.     if (handlePtr == (Fsio_PipeIOHandle *)NIL) {
  1045.     status = FAILURE;
  1046.     } else {
  1047.     Fsconsist_IOClientStatus(&handlePtr->clientList, clientID,
  1048.                  &reopenParamsPtr->use);
  1049.     (void)Fsconsist_IOClientReopen(&handlePtr->clientList, clientID,
  1050.                  &reopenParamsPtr->use);
  1051.     handlePtr->use.ref += reopenParamsPtr->use.ref;
  1052.     handlePtr->use.write += reopenParamsPtr->use.write;
  1053.     Fsutil_HandleRelease(handlePtr, TRUE);
  1054.     status = SUCCESS;
  1055.     }
  1056.     *outSizePtr = 0;
  1057.     *outDataPtr = (ClientData)NIL;
  1058.     return(status);
  1059. }
  1060.  
  1061. /*
  1062.  *----------------------------------------------------------------------
  1063.  *
  1064.  * Fsio_PipeClientKill --
  1065.  *
  1066.  *    Clean up after a crashed client.  Note, this doesn't handle the
  1067.  *    obscure case of one end of a pipe being duplicated and then
  1068.  *    one of the sharers migrating to a host which crashes.  In this
  1069.  *    funny case we'll wrongly think that all users of one end of
  1070.  *    the pipe have crashed.
  1071.  *
  1072.  * Results:
  1073.  *      SUCCESS.
  1074.  *
  1075.  * Side effects:
  1076.  *      Removes the client (if applicable) from the pipe's set of clients.
  1077.  *    This will cause a FS_BROKEN_PIPE error unless the pipe is re-opened,
  1078.  *    which might happen in a network partition.  This unlocks the handle.
  1079.  *
  1080.  *----------------------------------------------------------------------
  1081.  */
  1082. void
  1083. Fsio_PipeClientKill(hdrPtr, clientID)
  1084.     Fs_HandleHeader *hdrPtr;     /* Handle to clean up */
  1085.     int clientID;        /* Host assumed down */
  1086. {
  1087.     register Fsio_PipeIOHandle *handlePtr = (Fsio_PipeIOHandle *)hdrPtr;
  1088.     int refs, writes, execs;
  1089.     register ReturnStatus status;
  1090.  
  1091.     Fsconsist_IOClientKill(&handlePtr->clientList, clientID, &refs, &writes, &execs);
  1092.     status = PipeCloseInt(handlePtr, refs, writes, FALSE);
  1093.     if (status != FS_FILE_REMOVED) {
  1094.     Fsutil_HandleUnlock(handlePtr);
  1095.     }
  1096. }
  1097.  
  1098.  
  1099. /*
  1100.  *----------------------------------------------------------------------
  1101.  *
  1102.  * Fsio_PipeScavenge --
  1103.  *
  1104.  *    Scavenge a pipe.  The handle might be usless if all its
  1105.  *    client's have crashed.
  1106.  *
  1107.  * Results:
  1108.  *      TRUE if the handle was removed.
  1109.  *
  1110.  * Side effects:
  1111.  *      Unlocks the pipe's handle.
  1112.  *
  1113.  *----------------------------------------------------------------------
  1114.  */
  1115. Boolean
  1116. Fsio_PipeScavenge(hdrPtr)
  1117.     Fs_HandleHeader *hdrPtr;     /* Handle about to be deleted */
  1118. {
  1119. #ifdef notdef
  1120.     register Fsio_PipeIOHandle *handlePtr = (Fsio_PipeIOHandle *)hdrPtr;
  1121.     if (List_IsEmpty(&handlePtr->clientList) &&
  1122.     (handlePtr->flags == (FSIO_PIPE_WRITER_GONE|FSIO_PIPE_READER_GONE))) {
  1123.     /*
  1124.      * Never scavenge pipe handles.  Regular recovery cleanup
  1125.      * should invoke the pipe close routines and do proper cleanup.
  1126.      */
  1127.     free(handlePtr->buffer);
  1128.     Fsutil_WaitListDelete(&handlePtr->readWaitList);
  1129.     Fsutil_WaitListDelete(&handlePtr->writeWaitList);
  1130.     Fsutil_HandleRemove(hdrPtr);
  1131.     fs_Stats.object.pipes--;
  1132.     return(TRUE);
  1133.     }
  1134. #endif notdef
  1135.     Fsutil_HandleUnlock(hdrPtr);
  1136.     return(FALSE);
  1137. }
  1138.  
  1139.  
  1140. /*
  1141.  *----------------------------------------------------------------------
  1142.  *
  1143.  * Fsio_PipeRecovTestUseCount --
  1144.  *
  1145.  *    For recovery testing, return the use count on the io handle.
  1146.  *
  1147.  * Results:
  1148.  *      The use count.
  1149.  *
  1150.  * Side effects:
  1151.  *      None.
  1152.  *
  1153.  *----------------------------------------------------------------------
  1154.  */
  1155. int
  1156. Fsio_PipeRecovTestUseCount(handlePtr)
  1157.     Fsio_PipeIOHandle *handlePtr;
  1158. {
  1159.     return handlePtr->use.ref;
  1160. }
  1161.